﻿using System;
using Tiny.Imaging.Filter.PixelLibrary;

namespace Tiny.Imaging.Filter.PointFilter
{
    public class ChannelsFilter : BaseFilter.BaseFilter
    {
        private readonly int[] _bMapping;
        private readonly int[] _gMapping;
        private readonly int[] _rMapping;

        public ChannelsFilter(int r = 0, int g = 0, int b = 0, Func<int, int, int> blend = null, int opacity = 100)
            : base(blend, opacity)
        {
            PrePopulate(ref _rMapping, r);
            PrePopulate(ref _gMapping, g);
            PrePopulate(ref _bMapping, b);
        }

        public override int Process(Rgba rgba)
        {
            rgba.R = _rMapping[rgba.R];
            rgba.G = _gMapping[rgba.G];
            rgba.B = _bMapping[rgba.B];

            return rgba.ToInteger();
        }

        private void PrePopulate(ref int[] mapping, int factor)
        {
            mapping = new int[256];
            float fac = factor / 100.0f;
            if (factor > 0)
            {
                for (int i = 0; i < 256; ++i)
                {
                    mapping[i] = Blend(i, MathLibrary.MathLibrary.Clamp(i + ((255 - i) * fac)));
                }
            }
            else if (factor < 0)
            {
                for (int i = 0; i < 256; ++i)
                {
                    mapping[i] = Blend(i, MathLibrary.MathLibrary.Clamp(i - (i * Math.Abs(fac))));
                }
            }
            else
            {
                for (int i = 0; i < 256; ++i)
                {
                    mapping[i] = Blend(i, i);
                }
            }
        }
    }
}